#ifdef VoxelMapGeneration
flat out int v_MainDirection;
#endif

float _GetPointToPlaneDistance(int i, int pln)
{
#ifdef Clipping 
  if(pln == 0)
    return VertexIn[i]._SBSignedDistance4.x;
  else if(pln == 1)
    return VertexIn[i]._SBSignedDistance4.y;
  else if(pln == 2)
    return VertexIn[i]._SBSignedDistance4.z;
  else if(pln == 3)
    return VertexIn[i]._SBSignedDistance4.w;
  else if(pln == 4)
    return VertexIn[i]._SBSignedDistance2.x;
  else if(pln == 5)
    return VertexIn[i]._SBSignedDistance2.y;
#else
  return 0.0;
#endif
}

void _EmitVertex(int oStr)
{
#ifdef ComputeSectionProfileInGS_SinglePass
  EmitStreamVertex(oStr);
#else
  EmitVertex();
#endif
}

void _EndPrimitive(int oStr)
{
#ifdef ComputeSectionProfileInGS_SinglePass
  EndStreamPrimitive(oStr);
#else
  EndPrimitive();
#endif
}

void _CalculateSectionProfile(int oStr)
{
#ifdef Clipping 
  for(int pln = 0; pln < kClipPlanesCount; pln++)
  {
	for(int i = 0; i < gl_in.length(); i++)
    {
	  int j=i+1;
	  if(j==gl_in.length())
	    j=0;

      float di = _GetPointToPlaneDistance(i, pln);
      float dj = _GetPointToPlaneDistance(j, pln);
      
      if(di * dj < 0.0)
      { 
	    di = abs(di);
        dj = abs(dj);
        
        vec3 pti = VertexIn[i]._SBViewPos;
        vec3 ptj = VertexIn[j]._SBViewPos;
        vec3 vij = ptj - pti;
        vec3 pt = pti + vij*(di/(di+dj));
        
		vec4 ptView = vec4(pt, 1);
        
        vec4 signedDistance4;
        vec2 signedDistance2;  	    
        _vComputePlaneClipping(ptView, signedDistance4, signedDistance2);	    
		signedDistance4 += vec4(0.0005);
        vSetClippingDistance(signedDistance4, signedDistance2);

	    GeomOut._SBWorldPos = (vGetWorldViewInverseTransposeMatrix() * ptView).xyz;
		//GeomOut._SBViewPos = ptView.xyz;
		GeomOut._SBWorldN = VertexIn[i]._SBWorldN;
		
        //_CopyVaryings(i); //Automatic copy of needed varyings	    

		gl_Position = vGetProjMatrix() * ptView; 
        _EmitVertex(oStr);
  	  }
	} // for all vertices
	
	_EndPrimitive(oStr);

  }// for all clipping planes
#endif
}

void main()
{
#ifdef ComputeSectionProfileInGS_AdditionalPass 
  _CalculateSectionProfile(0);
  return;
#endif
  
#ifdef _PDSFX1_GS_CommonValues
  ComputeCommonValues();
#endif

#ifdef VoxelMapGeneration
  vec3 n = vAbs(vCross((VertexIn[1]._SBViewPos - VertexIn[0]._SBViewPos).xyz, (VertexIn[2]._SBViewPos - VertexIn[0]._SBViewPos).xyz));
  
  mat4 voxelTransfoProj;
  if (n.z > n.x && n.z > n.y)       v_MainDirection = 0;  // oX
  else if (n.x > n.y && n.x > n.z)  v_MainDirection = 1;  // oY
  else                              v_MainDirection = 2;  // oZ

  voxelTransfoProj = cb_Voxel_Auto.tranfoViewToViewProj[v_MainDirection];
#endif

  for(int i = 0; i < gl_in.length(); i++)
  {
    vec4 pos = gl_in[i].gl_Position;

#ifdef _PDSFX1_GS_ClipSpacePos
    ProcessClipSpacePosition(i, pos);
#endif

#ifdef VoxelMapGeneration
    pos = voxelTransfoProj * vec4(VertexIn[i]._SBViewPos, 1.0);
#endif

    gl_Position = pos;   

#ifndef VIEW_SPACE_ONLY
    GeomOut._SBWorldPos = VertexIn[i]._SBWorldPos;
#endif
    
    GeomOut._SBViewPos = VertexIn[i]._SBViewPos;
    GeomOut._SBWorldN = VertexIn[i]._SBWorldN;

#ifdef NeedUVs
    GeomOut._SBuv = VertexIn[i]._SBuv;
#endif

#ifdef HasDecal
    GeomOut._SBLegUVCoord = VertexIn[i]._SBLegUVCoord;
#endif

#ifdef PDSFX1
    GeomOut._SBstpq1 = VertexIn[i]._SBstpq1;
    GeomOut._SBstpq2 = VertexIn[i]._SBstpq2;
#endif

#ifdef LightMap
    GeomOut._SBLightMapUVs = VertexIn[i]._SBLightMapUVs;
#endif

#ifdef UseTangentSpace
    GeomOut._SBWorldT = VertexIn[i]._SBWorldT;
    GeomOut._SBWorldB = VertexIn[i]._SBWorldB;
#endif

#if defined NeedProjPos
    GeomOut._SBProjPos = VertexIn[i]._SBProjPos;
#endif

#if defined NeedViewPos
    GeomOut._SBViewPosPostTransform = VertexIn[i]._SBViewPosPostTransform;
#endif

#ifdef Clipping 
    GeomOut._SBSignedDistance4 = VertexIn[i]._SBSignedDistance4;
    GeomOut._SBSignedDistance2 = VertexIn[i]._SBSignedDistance2;
#endif     
    
#ifdef GroundClipping
    GeomOut._SBSignedDistanceGround = VertexIn[i]._SBSignedDistanceGround;
#endif

#ifdef DecalLighting
    GeomOut.vObjectSpacePosition = VertexIn[i].vObjectSpacePosition;
#endif

#ifdef _PDSFX1_GS_Varyings
    ComputeVaryingValues(i);
#endif

    _CopyVaryings(i); //Automatic copy of needed varyings

    EmitVertex();
  }

  EndPrimitive();

#ifdef _PDSFX1_GS_OutputStreams
  ComputeCustomStreams();
#endif
}
